If a database transaction is specified to be an atomic transaction, then the effect of that transaction on a database must either be entirely complete if that transaction succeeds, or entirely absent if that transaction fails. A partial effect is unsatisfactory. Certain services, such as the Java Transaction Service (JTS), implement a protocol that, when followed, guarantees that any effect of an atomic transaction on a database will be either completed or negated.
When a multi-state transaction is committed, the transaction enters, in turn, each one of a sequence of defined states. For example, JTS implements a sequence of five states: “active,” “preparing,” “prepared,” “completing,” and “completed.” At any given time when a transaction is in the process of committing, the transaction will be in one of these states. While a transaction is in any of these states, a process involved in the transaction may fail. For example, a client process and a server process may both participate in a transaction (in concert with a JTS process), and either the client or the server may fail. Depending on whether the client or the server failed, and depending on the state of the transaction at the time of the failure, the protocol specifies that the transaction should be either completed or negated.
When a process fails, that process may cease execution. If the protocol specifies that the transaction should be completed, then the failed process should be restarted. The JTS may participate in restarting the failed transaction. As a result of the failed process being restarted, certain modifications (those relating to the transaction) will be made to one or more databases.
If, on the other hand, the protocol specifies that the transaction should not be completed, then the failed process should not be restarted. As a result of the failed process not being restarted, certain modifications will not be made to the one or more databases.
Testing whether the participants in the transaction actually behave according to the protocol can be a difficult task. One problem is how to cause a desired participant to fail during a desired transaction state. Because the states of a transaction transition swiftly, a human user may have great difficulty in manually causing a participant to fail during the desired state. Another problem, given that each transaction participant may or may not be executing after a transaction commits, is how to successively test the behavior of a participant relative to a failure in each state without requiring undue effort from a human user.